package com.solution.service;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.log4j.Logger;
import org.jboss.annotation.ejb.RemoteBinding;

import com.solution.constant.CommunicationConstants;
import com.solution.constant.StatusConstants;
import com.solution.dao.CommunicationDAO;
import com.solution.dao.DAOFactory;
import com.solution.exception.DAOException;
import com.solution.exception.ServiceBeanException;
import com.solution.exception.ServiceLocatorException;
import com.solution.model.Communication;
import com.solution.util.SearchVO;

@Stateless
@Remote(CommunicationService.class)
@RemoteBinding(jndiBinding="CommunicationService")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class CommunicationServiceImpl implements CommunicationService{

	/**
	 * Logger instance.
	 */
	private Logger log = Logger.getLogger(CommunicationServiceImpl.class.getName());
	
	@EJB
	private CommunicationTypeService communicationTypeService;
	/**
	 * DAO instance.
	 */
	private CommunicationDAO communicationDao = (CommunicationDAO)DAOFactory.getDAOInstance(CommunicationDAO.class.getName());
	
	private static final String QUEUE_CONNECTION_FACTORY = "ConnectionFactory";
	private static final String LONG_PROCESS_QUEUE = "queue/communication/MessageQueue";

	public void sendSMS(String mobileNumber, String message, long ownerId, String userName) throws ServiceBeanException{
		log.debug("Entering :: CommunicationServiceImpl:sendSMS()");
		Communication communication = new Communication();
		communication.setMobileNumber(mobileNumber);
		communication.setContent(message);
		communication.setCommunicationType(communicationTypeService.fetchCommunicationTypeByName(CommunicationConstants.COMMUNICATION_TYPE_SMS));
		communication.setCreatedBy(userName);
		communication.setCreatedOn(new Date());
		communication.setStatus(StatusConstants.ACTIVE);
		sendMessage(communication, QUEUE_CONNECTION_FACTORY, LONG_PROCESS_QUEUE);
	}
	
	public void sendEmail(String email, String message, String subject, long ownerId, String userName) throws ServiceBeanException{
		log.debug("Entering :: CommunicationServiceImpl:sendSMS()");
		Communication communication = new Communication();
		communication.setEmailId(email);
		communication.setEmailSubject(subject);
		communication.setContent(message);
		communication.setCommunicationType(communicationTypeService.fetchCommunicationTypeByName(CommunicationConstants.COMMUNICATION_TYPE_EMAIL));
		communication.setCreatedBy(userName);
		communication.setCreatedOn(new Date());
		communication.setStatus(StatusConstants.ACTIVE);
		sendMessage(communication, QUEUE_CONNECTION_FACTORY, LONG_PROCESS_QUEUE);
	}
	
	public List<Communication> getCommunications(SearchVO searchVO)throws ServiceBeanException{
		try{
			return communicationDao.search(searchVO);
		}
		catch(DAOException de){
			log.error("Exception while reading Communication.");
			throw new EJBException(de);
		}
	}
	
	private static void sendMessage(Serializable payload, String connectionFactoryJndiName, String destinationJndiName){
        try {
            ConnectionFactory connectionFactory = null;
            Connection connection = null;
            Session session = null;
            Destination destination = null;
            MessageProducer messageProducer = null;
            ObjectMessage message = null;
            connectionFactory = getJmsConnectionFactory(connectionFactoryJndiName);
            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = getJmsDestination(destinationJndiName);
            messageProducer = session.createProducer(destination);
            message = session.createObjectMessage(payload);
            messageProducer.send(message);
            messageProducer.close();
            session.close();
            connection.close();
        } catch (JMSException je) {
            throw new EJBException(je);
        } catch (ServiceLocatorException sle) {
            throw new EJBException(sle);
        }
	}
	
	private static ConnectionFactory getJmsConnectionFactory(String jmsConnectionFactoryJndiName)throws ServiceLocatorException{
		ConnectionFactory jmsConnectionFactory = null;
		try {
		   Context ctx = new InitialContext();
		   jmsConnectionFactory = (ConnectionFactory) ctx.lookup(jmsConnectionFactoryJndiName);
		}
		catch (ClassCastException cce) {
		   throw new ServiceLocatorException(cce);
		}
		catch (NamingException ne) {
		   throw new ServiceLocatorException(ne);
		}
		return jmsConnectionFactory;
	}
	
	private static Destination getJmsDestination(String jmsDestinationJndiName) throws ServiceLocatorException{
		Destination jmsDestination = null;
		try {
			Context ctx = new InitialContext();
			jmsDestination = (Destination) ctx.lookup(jmsDestinationJndiName);
		} catch (ClassCastException cce) {
			throw new ServiceLocatorException(cce);
		} catch (NamingException ne) {
			throw new ServiceLocatorException(ne);
		}
		return jmsDestination;
	}
}
